home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume26 / opcom-2.1 / part01 next >
Encoding:
Text File  |  1993-04-10  |  32.8 KB  |  1,310 lines

  1. Newsgroups: comp.sources.unix
  2. From: rccarel@urc.tue.nl (Carel Braam)
  3. Subject: v26i119: opcom-2.1 - permit unprivileged users to run selected commands, Part01/01
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: rccarel@urc.tue.nl (Carel Braam)
  8. Posting-Number: Volume 26, Issue 119
  9. Archive-Name: opcom-2.1/part01
  10.  
  11. Opcom is a program, that enables users, belonging to a special group to
  12. execute a limited set of commands with another userid or groupid.  This
  13. makes it possible to perform daily system administration tasks without
  14. having the full privileges of root.  It is also possible to use opcom to
  15. execute shell scripts with privileges without having to rely on insecure
  16. suid-scripts.
  17.  
  18.     rccarel@urc.tue.nl (Carel Braam)
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 1 (of 1)."
  27. # Contents:  ENHANCEMENTS MANIFEST Makefile README UNSHAR.HDR config
  28. #   detab.c opcom.c srctoman sysdep
  29. # Wrapped by vixie@gw.home.vix.com on Sun Apr 11 01:55:17 1993
  30. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  31. if test -f 'ENHANCEMENTS' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'ENHANCEMENTS'\"
  33. else
  34. echo shar: Extracting \"'ENHANCEMENTS'\" \(1375 characters\)
  35. sed "s/^X//" >'ENHANCEMENTS' <<'END_OF_FILE'
  36. X            Opcom release 2.1 enhancements
  37. X            ==============================
  38. X
  39. X
  40. X
  41. X- Root is assumed to belong to all groups, so he is allowed to execute all
  42. X  opcom-commands.
  43. X
  44. X- If a userid was not mentioned in /etc/group with the group assigned to him
  45. X  in /etc/passwd, he was not allowed to execute commands for that group.
  46. X  This has been fixed.
  47. X
  48. X- The effective groupid is now also used to determine whether the user is
  49. X  allowed to execute a command.
  50. X
  51. X- In this version it is also possible to define opcom-commands that can
  52. X  be called by any userid. In that case operator-group must be an '*'.
  53. X  This makes it possible to write shell scripts that will be executed with
  54. X  root privileges. So the use of suid-shell scripts (a serious security hole)
  55. X  can be avoided.
  56. X
  57. X- If opcom is called without arguments, the list of valid commands is printed.
  58. X
  59. X- The manual page has been moved from chapter 8 to chapter 1.
  60. X
  61. X- Optionally opcom usage is reported via syslogd(8). See README and config
  62. X  for details.
  63. X
  64. X- The environment is cleared before the environment variables are set to the
  65. X  values mentioned in opcom(1).
  66. X
  67. X- If opcom is not running with root as effective user, a warning is printed.
  68. X  This to facilitate debugging.
  69. X
  70. X- All typed functions now return values. This improves portability.
  71. X
  72. X- Some elementary checking is done on the argument list.
  73. X
  74. X
  75. X                        Carel Braam, january 1991
  76. END_OF_FILE
  77. if test 1375 -ne `wc -c <'ENHANCEMENTS'`; then
  78.     echo shar: \"'ENHANCEMENTS'\" unpacked with wrong size!
  79. fi
  80. # end of 'ENHANCEMENTS'
  81. fi
  82. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  83.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  84. else
  85. echo shar: Extracting \"'MANIFEST'\" \(424 characters\)
  86. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  87. X   File Name        Archive #    Description
  88. X-----------------------------------------------------------
  89. X ENHANCEMENTS               1    
  90. X MANIFEST                   1    This shipping list
  91. X Makefile                   1    
  92. X README                     1    
  93. X UNSHAR.HDR                 1    
  94. X config                     1    
  95. X detab.c                    1    
  96. X opcom.c                    1    
  97. X srctoman                   1    
  98. X sysdep                     1    
  99. END_OF_FILE
  100. if test 424 -ne `wc -c <'MANIFEST'`; then
  101.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  102. fi
  103. # end of 'MANIFEST'
  104. fi
  105. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  106.   echo shar: Will not clobber existing file \"'Makefile'\"
  107. else
  108. echo shar: Extracting \"'Makefile'\" \(1926 characters\)
  109. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  110. X#++
  111. X# NAME
  112. X#    Makefile
  113. X# SUMMARY
  114. X#    makefile for opcom.
  115. X# AUTHOR(S)
  116. X#
  117. X#      Carel Braam (rccarel@urc.tue.nl)
  118. X#      Eindhoven University of Technology
  119. X#      Computing Centre
  120. X#      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  121. X# CREATION DATE
  122. X#    Thu Jan  5 10:41:57 MET 1989
  123. X# LAST MODIFICATION
  124. X#    Thu Jan 10 10:02:53 MET 1991
  125. X# VERSION/RELEASE
  126. X#    2.1
  127. X#--
  128. X
  129. X# System dependent variables
  130. X
  131. CC = cc
  132. CDEFS =
  133. CFLAGS =
  134. LFLAGS = -h
  135. BINDIR = /usr/local/bin
  136. MANDIR = /usr/local/man
  137. X
  138. X# End system dependent variables
  139. X
  140. CSOURCES = opcom.c
  141. HFILES = sysdep
  142. SHELLS = config
  143. MAKEFILES = Makefile
  144. OPSOURCES = $(CSOURCES) $(HFILES) $(SHELLS) $(MAKEFILES) ENHANCEMENTS README
  145. USOURCES = detab.c srctoman
  146. SOURCES = $(OPSOURCES) $(USOURCES)
  147. X
  148. all:    opcom
  149. X
  150. sysdep.h: sysdep config
  151. X    sh config sysdep >sysdep.h
  152. X
  153. man:    opcom.1
  154. X
  155. opcom.1: opcom.c config detab
  156. X    sh srctoman -L opcom.c | sh config >opcom.1
  157. X
  158. X# Lint.
  159. X
  160. lint:    sysdep.h
  161. X    lint $(LFLAGS) $(CDEFS) opcom.c
  162. X
  163. X
  164. detab: detab.c
  165. X    $(CC) $(CFLAGS) $(CDEFS) detab.c -o detab
  166. X
  167. opcom: opcom.c sysdep.h
  168. X    $(CC) $(CFLAGS) $(CDEFS) opcom.c -o opcom
  169. X
  170. X# Installation and update.
  171. X
  172. install: opcom
  173. X    cp opcom $(BINDIR)
  174. X    cd $(BINDIR); chown root opcom; chmod u+s opcom
  175. X
  176. installman: man
  177. X     cp opcom.1 $(MANDIR)/man1
  178. X     rm -f $(MANDIR)/cat1/opcom.1
  179. X
  180. archive: $(OPSOURCES)
  181. X    archive $(OPSOURCES)
  182. X
  183. release: $(OPSOURCES)
  184. X    modsource +1 $(CSOURCES)
  185. X    modsource +2 $(CSOURCES)
  186. X    modsource +1 -c $(HFILES)
  187. X    modsource +2 -c $(HFILES)
  188. X    modsource +1 -mk $(MAKEFILES) README
  189. X    modsource +2 -mk $(MAKEFILES) README
  190. X    modsource +1 - $(SHELLS)
  191. X    modsource +2 - $(SHELLS)
  192. X    archive $(OPSOURCES)
  193. X
  194. version: $(OPSOURCES)
  195. X    modsource -1 $(CSOURCES)
  196. X    modsource -1 -c $(HFILES)
  197. X    modsource -1 -mk $(MAKEFILES) README
  198. X    modsource -1 - $(SHELLS)
  199. X    archive $(OPSOURCES)
  200. X
  201. shar:    $(SOURCES)
  202. X    rm -f Part?? Part??.Z
  203. X    makekit $(SUBDIRS) $(SOURCES) $(DIRENT)
  204. X
  205. clean:
  206. X    -rm -f *.BAK *.o opcom detab opcom.1 tmp.* sysdep.h \
  207. X    nohup.out core Part?? Part??.Z
  208. END_OF_FILE
  209. if test 1926 -ne `wc -c <'Makefile'`; then
  210.     echo shar: \"'Makefile'\" unpacked with wrong size!
  211. fi
  212. # end of 'Makefile'
  213. fi
  214. if test -f 'README' -a "${1}" != "-c" ; then 
  215.   echo shar: Will not clobber existing file \"'README'\"
  216. else
  217. echo shar: Extracting \"'README'\" \(2058 characters\)
  218. sed "s/^X//" >'README' <<'END_OF_FILE'
  219. Opcom is a program, that enables users, belonging to a special group to
  220. execute a limited set of commands with another userid or groupid.
  221. This makes it possible to perform daily system administration tasks without
  222. having the full privileges of root.
  223. It is also possible to use opcom to execute shell scripts with privileges
  224. without having to rely on insecure suid-scripts.
  225. X
  226. X
  227. Carel Braam
  228. X
  229. internet: rccarel@urc.tue.nl     | Computing Centre
  230. bitnet:      rccarel@heitue5.BITNET | Eindhoven University of Technology
  231. phone:      040-472158         | Den Dolech 2, P.O. Box 513
  232. home:      040-810381         | 5600 MB Eindhoven, The Netherlands
  233. X
  234. X
  235. X                INSTALLATION NOTES
  236. X                ==================
  237. X
  238. Before you start off adapt the file config to your local needs.
  239. All system dependent variables are set between the comment
  240. X
  241. X#    *** System dependent variables ***
  242. X
  243. and  the comment
  244. X
  245. X#    *** End system dependent variables ***
  246. X
  247. Currently the following variables can be set:
  248. X
  249. SYSTEM        Set SYSTEM to BSD for bsd systems and to SYSV for system v.
  250. SYSLOG        Set SYSLOG to USE_SYSLOG if you want to report opcom usage via
  251. X        syslogd(8) and to NO_SYSLOG otherwise.
  252. X        SYSLOG must also be set to NO_SYSLOG if your system does not
  253. X        support syslogd(8).
  254. OPCOMDIR    The directory for the files COMMANDS and PROFILE.
  255. COMMANDS    The file containing the commands, that are allowed.
  256. PROFILE        The file containing the profile to be executed.
  257. X
  258. As well the manual page opcom.1 as sysdep.h are dependent on config.
  259. To make opcom just enter make.
  260. The manual page can be created by entering make man.
  261. Then as super user type "make install" to install opcom and "make installman"
  262. to install the manual page.
  263. See the makefile for the definition of the local bin directory and the local
  264. manual directory.
  265. X
  266. X#++
  267. X# AUTHOR(S)
  268. X#
  269. X#      Carel Braam (rccarel@urc.tue.nl)
  270. X#      Eindhoven University of Technology
  271. X#      Computing Centre
  272. X#      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  273. X# CREATION DATE
  274. X#    Thu Jan  5 11:25:04 MET 1989
  275. X# LAST MODIFICATION
  276. X#    Thu Jan 10 10:02:54 MET 1991
  277. X# VERSION/RELEASE
  278. X#    2.1
  279. X#--
  280. END_OF_FILE
  281. if test 2058 -ne `wc -c <'README'`; then
  282.     echo shar: \"'README'\" unpacked with wrong size!
  283. fi
  284. # end of 'README'
  285. fi
  286. if test -f 'UNSHAR.HDR' -a "${1}" != "-c" ; then 
  287.   echo shar: Will not clobber existing file \"'UNSHAR.HDR'\"
  288. else
  289. echo shar: Extracting \"'UNSHAR.HDR'\" \(1141 characters\)
  290. sed "s/^X//" >'UNSHAR.HDR' <<'END_OF_FILE'
  291. Return-Path: root@tue.nl
  292. Received: by cognition.pa.dec.com; id AA07850; Fri, 29 May 92 02:27:07 -0700
  293. Received: by inet-gw-2.pa.dec.com; id AA29935; Fri, 29 May 92 02:24:41 -0700
  294. Received: from tuegate.tue.nl by sun4nl.nluug.nl with SMTPid AA14982 (5.65b/CWI-3.3); Fri, 29 May 1992 11:23:05 +0200
  295. Received: by tuegate.tue.nl id AA23498  (5.65c/IDA-1.4.4 for nluug.nl!comp-sources-unix); Fri, 29 May 1992 11:25:47 +0200
  296. To: comp-sources-unix@nluug.nl
  297. Path: tuegate.tue.nl!rc6.urc.tue.nl!rccarel
  298. XFrom: rccarel@rc6.urc.tue.nl (Carel Braam)
  299. Newsgroups: comp.sources.unix
  300. Subject: opcom - execute an operator command
  301. Message-Id: <rccarel.707131492@rc6.urc.tue.nl>
  302. Date: 29 May 92 09:24:52 GMT
  303. Sender: root@tue.nl
  304. Reply-To: rccarel@urc.tue.nl
  305. Lines: 1241
  306. X
  307. X
  308. X
  309. Version 2.1 of opcom was posted before, but it never showed up. So I
  310. post it again, because this version is more secure than the previous one.
  311. One of the enhancements is that creates a complete new environment so
  312. that no original environment variable is retained (see CERT advisory of
  313. May 27, 1992).
  314. X
  315. X                    Carel Braam
  316. X                    Eindhoven University of Technology
  317. X                    The Netherlands
  318. X
  319. END_OF_FILE
  320. if test 1141 -ne `wc -c <'UNSHAR.HDR'`; then
  321.     echo shar: \"'UNSHAR.HDR'\" unpacked with wrong size!
  322. fi
  323. # end of 'UNSHAR.HDR'
  324. fi
  325. if test -f 'config' -a "${1}" != "-c" ; then 
  326.   echo shar: Will not clobber existing file \"'config'\"
  327. else
  328. echo shar: Extracting \"'config'\" \(1053 characters\)
  329. sed "s/^X//" >'config' <<'END_OF_FILE'
  330. X: use /bin/sh
  331. X
  332. X# opcom configuration script.
  333. X#
  334. X# In the first part of this script the directories and the administration
  335. X# for opcom are defined.
  336. X# Refer to all of these only by the environment variables defined here.
  337. X
  338. X#++
  339. X# AUTHOR(S)
  340. X#
  341. X#      Carel Braam (rccarel@urc.tue.nl)
  342. X#      Eindhoven University of Technology
  343. X#      Computing Centre
  344. X#      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  345. X# CREATION DATE
  346. X#    Thu Jan  5 11:09:45 MET 1989
  347. X# LAST MODIFICATION
  348. X#    Thu Jan 10 10:02:54 MET 1991
  349. X# VERSION/RELEASE
  350. X#    2.1
  351. X#--
  352. X
  353. X#    *** System dependent variables ***
  354. X
  355. SYSTEM=BSD        # must be BSD or SYSV (system v)
  356. X#SYSTEM=SYSV        # must be BSD or SYSV (system v)
  357. SYSLOG=USE_SYSLOG    # report opcom usage to syslogd
  358. X#SYSLOG=NO_SYSLOG    # don't report opcom usage
  359. X
  360. OPCOMDIR="/usr/local/lib/opcom"    
  361. COMMANDS="$OPCOMDIR/commands"        # command file
  362. PROFILE="$OPCOMDIR/profile"        # profile
  363. X
  364. X#    *** End system dependent variables ***
  365. X
  366. sed 's%XCOMMANDS%'"$COMMANDS"'%g
  367. X     s%XPROFILE%'"$PROFILE"'%g
  368. X     s%XSYSLOG%'"$SYSLOG"'%g
  369. X     s%XSYSTEM%'"$SYSTEM"'%g' $*
  370. END_OF_FILE
  371. if test 1053 -ne `wc -c <'config'`; then
  372.     echo shar: \"'config'\" unpacked with wrong size!
  373. fi
  374. # end of 'config'
  375. fi
  376. if test -f 'detab.c' -a "${1}" != "-c" ; then 
  377.   echo shar: Will not clobber existing file \"'detab.c'\"
  378. else
  379. echo shar: Extracting \"'detab.c'\" \(1053 characters\)
  380. sed "s/^X//" >'detab.c' <<'END_OF_FILE'
  381. X/*++
  382. X/* NAME
  383. X/*    detab 1
  384. X/* SUMMARY
  385. X/*    expand tabs to blanks
  386. X/* PROJECT
  387. X/*    documentation
  388. X/* SYNOPSIS
  389. X/*    detab
  390. X/* DESCRIPTION
  391. X/*    Detab is a filter that expands tab stops in its standard input
  392. X/*    to blanks. A tab stop distance of eight blanks is assumed.
  393. X/* BUGS
  394. X/*    This program does not handle backspaces.
  395. X/* AUTHOR(S)
  396. X/*    Wietse Venema
  397. X/*    Eindhoven University of Technology
  398. X/*    Department of Mathematics and Computer Science
  399. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  400. X/* CREATION DATE
  401. X/*    Sep 14 1985
  402. X/* LAST MODIFICATION
  403. X/*    Mon May  4 20:32:48 GMT+1:00 1987
  404. X/* VERSION/RELEASE
  405. X/*    1.3
  406. X/*--*/
  407. X
  408. X#include <stdio.h>
  409. X
  410. X#define BLANK    ' '
  411. X
  412. main()
  413. X{
  414. X    register int c;        /* character buffer */
  415. X    register int ccount = 0;    /* nr of characters printed on current line */
  416. X
  417. X    while ((c = getchar()) != EOF) {
  418. X    switch (c) {
  419. X
  420. X        case '\r':
  421. X        case '\n':  putchar(c);
  422. X            ccount = 0;
  423. X            break;
  424. X
  425. X        case '\t':  do { putchar(BLANK); } while (++ccount & 7);
  426. X            break;
  427. X
  428. X        default:    putchar(c);
  429. X            ccount++;
  430. X            break;
  431. X    }
  432. X    }
  433. X    exit(0);
  434. X}
  435. END_OF_FILE
  436. if test 1053 -ne `wc -c <'detab.c'`; then
  437.     echo shar: \"'detab.c'\" unpacked with wrong size!
  438. fi
  439. # end of 'detab.c'
  440. fi
  441. if test -f 'opcom.c' -a "${1}" != "-c" ; then 
  442.   echo shar: Will not clobber existing file \"'opcom.c'\"
  443. else
  444. echo shar: Extracting \"'opcom.c'\" \(13362 characters\)
  445. sed "s/^X//" >'opcom.c' <<'END_OF_FILE'
  446. X/*++
  447. X/* NAME
  448. X/*      opcom 1
  449. X/* SUMMARY
  450. X/*      execute an operator command.
  451. X/* SYNOPSIS
  452. X/*    .fi
  453. X/*    .B opcom 
  454. X/*     command [ arguments ]
  455. X/* DESCRIPTION
  456. X/*    .I Opcom
  457. X/*    enables users belonging to a special group (as defined in /etc/group)
  458. X/*    to execute a limited set of commands with another userid (e.g. root)
  459. X/*    or groupid. The file
  460. X/*    .I XCOMMANDS
  461. X/*    describes which commands are allowed for which groups and which
  462. X/*    userid (groupid) will be used.
  463. X/*    .br
  464. X/*    .I Command
  465. X/*    is a valid operator command if it matches an entry in
  466. X/*    .I XCOMMANDS.
  467. X/*    Those entries have the following form:
  468. X/*    
  469. X/*    path-name : operator-group : [ new-userid ] [ : [ new-groupid ]]
  470. X/*    
  471. X/*    .I Command
  472. X/*    matches an entry, if it is the basename of 
  473. X/*    .I path-name
  474. X/*    and if at least one of the following conditions holds:
  475. X/*    .IP \- 2.4
  476. X/*    .I operator-group
  477. X/*    is "*".
  478. X/*    .IP \- 2.4
  479. X/*    The real userid executing
  480. X/*    .I opcom
  481. X/*    is a member of the group
  482. X/*    .I operator-group
  483. X/*    (as defined in /etc/group).
  484. X/*    .IP \- 2.4
  485. X/*    The default group of the real userid, as defined in /etc/passwd,
  486. X/*    is equal to
  487. X/*    .I operator-group.
  488. X/*    .IP \- 2.4
  489. X/*    The effective groupid is that of
  490. X/*    .I operator-group.
  491. X/*    .RE
  492. X/*
  493. X/*    If
  494. X/*    .I command
  495. X/*    matches more than one entry, the first matching entry is selected.
  496. X/*    This allows multiple levels of privilege.
  497. X/*    If no match is found,
  498. X/*    .I opcom
  499. X/*    aborts with the message "access denied.".
  500. X/*
  501. X/*    The matching command is executed with the given
  502. X/*    .I arguments
  503. X/*    unless they contain characters which are special to /bin/sh (e.g. ;).
  504. X/*    .br
  505. X/*    If
  506. X/*    .I new-userid (new-groupid)
  507. X/*    is not empty, the effective and real userid (groupid) are set to
  508. X/*    .I new-userid (new-groupid).
  509. X/*    .br
  510. X/*    If
  511. X/*    .I new-userid (new-groupid)
  512. X/*    is empty, the effective and real userid (groupid)
  513. X/*    are set to the real userid (groupid).
  514. X/*
  515. X/*    The current environment is cleared and the following environment
  516. X/*    variables are set:
  517. X/*    .IP \- 2.4
  518. X/*    COMMAND to
  519. X/*    .I command.
  520. X/*    .IP \-
  521. X/*    ORGGROUP to the group name of the real groupid of the invoker of
  522. X/*    .I opcom.
  523. X/*    .IP \-
  524. X/*    GROUP to the group name of the real groupid executing
  525. X/*    .I command.
  526. X/*    .IP \-
  527. X/*    IFS to blank, tab and new line.
  528. X/*    .IP \-
  529. X/*    ORGUSER to the login name of the real userid of the invoker of
  530. X/*    .I opcom.
  531. X/*    .IP \-
  532. X/*    PATH to /
  533. X/*    .IP \-
  534. X/*    USER and LOGNAME to the login name of the real userid executing
  535. X/*    .I command.
  536. X/*    .RE
  537. X/*
  538. X/*    If the script 
  539. X/*    .I XPROFILE
  540. X/*    exists, this script will be executed
  541. X/*    within the (Bourne) shell that executes
  542. X/*    .I command.
  543. X/*    So changes to the environment (e.g. PATH) can be put there.
  544. X/*
  545. X/*    If
  546. X/*    .I opcom
  547. X/*    is called with no arguments, a list of valid commands for the
  548. X/*    user executing
  549. X/*    .I opcom
  550. X/*    is printed.
  551. X/* FILES
  552. X/*    XCOMMANDS
  553. X/*    XPROFILE
  554. X/*    /etc/group
  555. X/*    /etc/passwd
  556. X/* CAVEAT
  557. X/*    Beware of Trojan horses: don't allow commands with shell escapes.
  558. X/* BUGS
  559. X/*    Invalid entries in
  560. X/*    .I XCOMMANDS
  561. X/*    are skipped without warning.
  562. X/* DIAGNOSTICS
  563. X/*    In case of error
  564. X/*    .I opcom
  565. X/*    prints an error message on standard error and terminates
  566. X/*    with nonzero status.
  567. X/*    .br
  568. X/*    Commands executed by \fIopcom\fP are optionally reported via syslogd(8).
  569. X/* EXAMPLES
  570. X/*
  571. X/*    
  572. X/*    .I XCOMMANDS:
  573. X/*
  574. X/*    .nf
  575. X/*    .ft C
  576. X/*    /bin/fsck:operators:root
  577. X/*    /bin/dump:operators:root
  578. X/*    /bin/kill:operators:root
  579. X/*    /etc/lpc:operators:root
  580. X/*    /usr/ucb/lprm:operators:root
  581. X/*    /bin/mount:operators:root
  582. X/*    /bin/restore:operators:root
  583. X/*    /bin/shutdown:operators:root
  584. X/*    /bin/umount:operators:root
  585. X/*    /mgt/cas/bin/menu:ucadmin:root
  586. X/*    /usr/local/bin/lp-cancel:bcf:daemon:daemon
  587. X/*    /usr/local/bin/lp-move:bcf:daemon:daemon
  588. X/*    /usr/local/bin/lp-force:bcf:daemon:daemon
  589. X/*    /usr/local/bin/lp-sched:bcf:daemon:daemon
  590. X/*    /usr/local/bin/lp-shut:bcf:daemon:daemon
  591. X/*    /usr/local/lib/opcom/testenv:*:
  592. X/*
  593. X/*    .ft
  594. X/*    Invocation examples:
  595. X/*
  596. X/*    opcom lpc start lp
  597. X/*    opcom shutdown
  598. X/*    opcom lp-shut
  599. X/*    opcom testenv
  600. X/* AUTHOR(S)
  601. X/*
  602. X/*      Carel Braam (rccarel@urc.tue.nl)
  603. X/*      Eindhoven University of Technology
  604. X/*      Computing Centre
  605. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  606. X/* BUG REPORTS TO
  607. X/*    rccarel@urc.tue.nl
  608. X/* CREATION DATE
  609. X/*    Wed Jan  4 14:12:59 MET 1989
  610. X/* LAST MODIFICATION
  611. X/*    Thu Jan 10 10:02:52 MET 1991
  612. X/* VERSION/RELEASE
  613. X/*    2.1
  614. X/*--*/
  615. X
  616. X#include <stdio.h>
  617. X#include "sysdep.h"
  618. X#include <grp.h>
  619. X#include <pwd.h>
  620. X#include <sys/types.h>
  621. X#include <sys/stat.h>
  622. X#include <varargs.h>
  623. X#include <ctype.h>
  624. X#ifdef USE_SYSLOG
  625. X#include <syslog.h>
  626. extern int openlog ();
  627. extern void syslog ();
  628. X#endif
  629. X
  630. extern void exit ();
  631. extern void perror ();
  632. extern int errno;
  633. extern char *sys_errlist [];
  634. extern int sys_nerr;
  635. X
  636. extern int getegid ();
  637. extern int geteuid ();
  638. extern int getgid ();
  639. extern int setuid ();
  640. extern struct group *getgrgid ();
  641. extern struct group *getgrnam ();
  642. extern struct passwd *getpwnam ();
  643. extern struct passwd *getpwuid ();
  644. extern char *malloc ();
  645. extern int system ();
  646. X
  647. X#define WARN    0
  648. X#define ABORT    1
  649. X
  650. struct command {
  651. X    char name [64];
  652. X    char path [1024];
  653. X    char group [32];
  654. X    char new_group [32];
  655. X    char new_user [32];
  656. X};
  657. X
  658. void PERROR ();
  659. int check_group ();
  660. int copy_args ();
  661. void display_commands ();
  662. void error ();
  663. void exec_cmnd ();
  664. struct command *get_command ();
  665. struct command *parse_command ();
  666. X
  667. XFILE *command_file;
  668. int my_egid,
  669. X    my_gid,
  670. X    my_euid,
  671. X    my_uid;
  672. char orguser [32] = {0};
  673. char orggroup [32] = {0};
  674. char *nextitem ();
  675. void set_env ();
  676. void set_ids ();
  677. X
  678. char *progname;                /* used for diagnostics */
  679. X
  680. main (argc, argv)
  681. int argc;
  682. char **argv;
  683. X{
  684. X    int fd;
  685. X    struct command *command;
  686. X    struct group *group;
  687. X    struct passwd *passwd;
  688. X
  689. X    /* close all file descriptors > 2 */
  690. X    for (fd = 3; fd <= _NFILE; fd++)
  691. X    (void) close (fd);
  692. X    if (progname = strrchr (*argv, '/'))
  693. X    progname++;
  694. X    else
  695. X    progname = *argv;
  696. X    argv++;
  697. X    argc--;
  698. X
  699. X    my_euid = geteuid();
  700. X    if (my_euid != 0)
  701. X    error (WARN, "Warning: the effective userid is not root.");
  702. X    my_uid = getuid();
  703. X    if ((passwd = getpwuid (my_uid)) == NULL)
  704. X    error (ABORT, "cannot find passwd entry for userid %d.", my_uid);
  705. X    (void) strcpy (orguser, passwd->pw_name);
  706. X
  707. X    my_egid = getegid();
  708. X    my_gid = getgid();
  709. X    if ((group = getgrgid (my_gid)) != NULL)
  710. X    (void) strcpy (orggroup, group->gr_name);
  711. X
  712. X    if ((command_file = fopen (COMMANDS, "r")) == NULL)
  713. X    error (ABORT, "cannot open %s for reading.", COMMANDS);
  714. X    if (argc == 0) {
  715. X    display_commands ();
  716. X    exit (0);
  717. X    }
  718. X
  719. X    command = get_command (*argv);
  720. X    set_ids (command->new_user, command->new_group);
  721. X    (void) fclose (command_file);
  722. X    exec_cmnd (command, argc-1, argv+1);
  723. X    return (0);    /* makes lint happy    */
  724. X}
  725. X
  726. void display_commands ()
  727. X{
  728. X    struct command *command;
  729. X    int first = 1;
  730. X    int printit;
  731. X
  732. X    while ((command = parse_command ()) != NULL) {
  733. X    if (my_uid == 0) {    /* root has access to all commands */
  734. X        printit = 1;
  735. X    } else {
  736. X        printit = check_group (command->group);
  737. X    }
  738. X    if (printit) {
  739. X        if (first) {
  740. X        first = 0;
  741. X        (void) printf ("Valid opcom commands are:\n\n");
  742. X        }
  743. X        (void) printf ("%s (group %s)\n", command->name, command->group);
  744. X    }
  745. X    }
  746. X    if (first)    /* We didn't find valid commands    */
  747. X    error (ABORT, "access denied.");
  748. X}
  749. X
  750. X
  751. struct command *get_command (name)
  752. char *name;
  753. X{
  754. X    struct command *command;
  755. X
  756. X    while ((command = parse_command ()) != NULL) {
  757. X    if (strcmp (name, command->name) == 0) {
  758. X        if (my_uid == 0)    /* root has access to all commands */
  759. X        return (command);
  760. X        if (check_group (command->group))
  761. X        return (command);
  762. X    }
  763. X    }
  764. X    error (ABORT, "access denied.");
  765. X    return (NULL);
  766. X}
  767. X
  768. struct command *parse_command ()
  769. X{
  770. X    static char cmndbuf [BUFSIZ];
  771. X    static struct command command;
  772. X    char ch,
  773. X     *cmnd,
  774. X     *pc,
  775. X     *ptail,
  776. X     *pt;
  777. X
  778. X    while (fgets (cmndbuf, BUFSIZ, command_file) != NULL) {
  779. X    for (cmnd = cmndbuf; isspace (*cmnd); cmnd++);
  780. X    pt = command.path;
  781. X    ptail = cmnd;
  782. X    while (! (isspace (ch = *ptail) || (ch == ':') || (ch == 0))) {
  783. X        *pt++ = ch;
  784. X        ptail++;
  785. X    }
  786. X    *pt = 0;
  787. X    while (isspace (*ptail))
  788. X        ptail++;
  789. X    if (*ptail != ':')    /* invalid entry    */
  790. X        continue;
  791. X    pt = command.path;
  792. X    if ((pc = strrchr (pt, '/')) == NULL)
  793. X        pc = pt;
  794. X    else
  795. X        pc++;
  796. X    (void) strcpy (command.name, pc);
  797. X    ptail = nextitem (ptail+1, command.group);
  798. X    ptail = nextitem (ptail, command.new_user);
  799. X    ptail = nextitem (ptail, command.new_group);
  800. X    return (&command);
  801. X    }
  802. X    return (NULL);
  803. X}
  804. X
  805. char *nextitem (pstart, target)
  806. char *pstart,
  807. X     *target;
  808. X{
  809. X    char ch,
  810. X     *ps = pstart,
  811. X     *pt = target;
  812. X
  813. X    while (isspace (*ps))
  814. X        ps++;
  815. X    if (*ps == 0) {
  816. X        *pt = 0;
  817. X        return (ps);
  818. X    }
  819. X    for (ch = *ps; (ch != ':') & (ch != 0); ch = *++ps)
  820. X        *pt++ = ch;
  821. X    *pt-- = 0;
  822. X    for (ch = *pt; isspace (ch); ch = *pt--)
  823. X        *pt = 0;
  824. X    if (*ps == 0)
  825. X        return (ps);
  826. X    else
  827. X        return (ps+1);
  828. X}
  829. X
  830. int check_group (groupname)
  831. char *groupname;
  832. X{
  833. X    char **gr_list;
  834. X    struct group *group;
  835. X
  836. X    if (strcmp (groupname, "*") == 0)  /* matches everything */
  837. X    return (1);
  838. X    if ((group = getgrnam (groupname)) != NULL) {
  839. X    if (my_egid == group->gr_gid)    /* effective groupid */
  840. X        return (1);
  841. X    for (gr_list = group->gr_mem; *gr_list != NULL; gr_list++) {
  842. X        if (strcmp (orguser, *gr_list) == 0)
  843. X        return (1);
  844. X    }
  845. X    }
  846. X    return (0);
  847. X}
  848. X
  849. void set_ids (new_user, new_group)
  850. char *new_user,
  851. X     *new_group;
  852. X{
  853. X    struct group *group;
  854. X    struct passwd *passwd;
  855. X
  856. X    if (*new_group != 0) {
  857. X    /* not empty, must be set before uid is set     */
  858. X    if ((group = getgrnam (new_group)) == NULL)
  859. X        error (ABORT, "cannot find group entry for groupid %s.", new_group);
  860. X    if (setgid (group->gr_gid) < 0)
  861. X        PERROR (ABORT);
  862. X    }
  863. X    if (*new_user != 0) {    /* not empty     */
  864. X    if ((passwd = getpwnam (new_user)) == NULL)
  865. X        error (ABORT, "cannot find passwd entry for userid %s.", new_user);
  866. X    if (setuid (passwd->pw_uid) < 0)
  867. X        PERROR (ABORT);
  868. X    } else if (setuid (getuid ()) < 0)
  869. X    PERROR (ABORT);
  870. X}
  871. X
  872. void exec_cmnd (command, argc, argv)
  873. struct command *command;
  874. int argc;
  875. char **argv;
  876. X{
  877. X    unsigned cmnd_size = 0;
  878. X    int i,
  879. X    rslt;
  880. X    struct stat prstat;
  881. X    char 
  882. X     special,
  883. X     *args,
  884. X     *cmnd,
  885. X     *pa,
  886. X     *pc;
  887. X
  888. X    set_env (command->name, command->new_group, command->new_user);
  889. X    cmnd_size = strlen (command->path)+32;
  890. X    for (i = 0; i < argc; i++)
  891. X    cmnd_size += strlen (argv [i])+1;
  892. X    pc = cmnd = malloc (cmnd_size+strlen (PROFILE));
  893. X    if ((stat (PROFILE, &prstat) == 0) && (prstat.st_mode & 0400)) {
  894. X    /* We must execute the profile */
  895. X    (void) sprintf (pc, ". %s;", PROFILE);
  896. X    pc += strlen (pc);
  897. X    }
  898. X    pa = command->path;
  899. X    while (*pa != 0)
  900. X    *pc++ = *pa++;
  901. X    *pc++ = ' ';
  902. X    args = pc;
  903. X    special = copy_args (argc, argv, args);
  904. X
  905. X#ifdef USE_SYSLOG
  906. X# ifdef LOG_AUTH
  907. X    (void) openlog (progname, LOG_PID, LOG_AUTH);
  908. X# else
  909. X    (void) openlog (progname, LOG_PID);
  910. X# endif /* LOG_AUTH */
  911. X    syslog (LOG_NOTICE, "%s: \"%s %s\"", orguser, command, args);
  912. X#endif USE_SYSLOG
  913. X
  914. X    if (special != 0)    /* Special characters are not allowed    */
  915. X    error (ABORT, "'%c' illegal in argument list.", special);
  916. X    if ((rslt = system (cmnd)) < 0)
  917. X    PERROR (ABORT);
  918. X    exit (rslt);
  919. X}
  920. X
  921. int copy_args (argc, argv, args)
  922. int argc;
  923. char **argv;
  924. char *args;
  925. X{
  926. X    char *pa,
  927. X     special = 0;
  928. X
  929. X    while (argc-- > 0) {
  930. X    for (pa = *argv++; *pa != 0; pa++) {
  931. X        *args++ = *pa;
  932. X        /* Look for special characters and return the first one.    */
  933. X        if (special == 0) {
  934. X        switch (*pa & 0177) {
  935. X        case ';':
  936. X        case '>':
  937. X        case '`':
  938. X        case '&':
  939. X        case '|':
  940. X        case '^':
  941. X        case '\n':
  942. X            special = *pa; /* We got one */
  943. X        }
  944. X        }
  945. X    }
  946. X    *args++ = ' ';
  947. X    }
  948. X    *args = 0;    /* close string    */
  949. X    return (special);
  950. X
  951. X}
  952. X
  953. void set_env (name, new_group, new_user)
  954. char *name,
  955. X     *new_group,
  956. X     *new_user;
  957. X{
  958. X    extern char **environ;
  959. X
  960. X    static char envbuf [2048] = {0};
  961. X    char *penv = envbuf;
  962. X    static char *newenv [16] = {0};
  963. X    int next = 0;
  964. X
  965. X#define put_env {newenv [next++] = penv; penv += strlen (penv) + 1;}
  966. X
  967. X    (void) sprintf (penv, "IFS= \t\n");
  968. X    put_env;
  969. X    (void) sprintf (penv, "PATH=/");
  970. X    put_env;
  971. X    (void) sprintf (penv, "COMMAND=%s", name);
  972. X    if (orggroup [0] != 0) {
  973. X    (void) sprintf (penv, "ORGGROUP=%s", orggroup);
  974. X    put_env;
  975. X    }
  976. X    if (new_group [0] != 0) {
  977. X    (void) sprintf (penv, "GROUP=%s", new_group);
  978. X    put_env;
  979. X    }
  980. X    (void) sprintf (penv, "ORGUSER=%s", orguser);
  981. X    put_env;
  982. X    if (*new_user == 0) {
  983. X    (void) sprintf (penv, "USER=%s", orguser);
  984. X    put_env;
  985. X    (void) sprintf (penv, "LOGNAME=%s", orguser);
  986. X    put_env;
  987. X    } else {
  988. X    (void) sprintf (penv, "USER=%s", new_user);
  989. X    put_env;
  990. X    (void) sprintf (penv, "LOGNAME=%s", new_user);
  991. X    put_env;
  992. X    }
  993. X    environ = newenv;
  994. X}
  995. X
  996. void PERROR (why)
  997. int why;
  998. X{
  999. X    perror (progname);
  1000. X    if (why == ABORT)
  1001. X    exit (1);
  1002. X}
  1003. X
  1004. X/* error - barf and quit */
  1005. X
  1006. X/* VARARGS1 */
  1007. X
  1008. void error (va_alist)
  1009. va_dcl
  1010. X{
  1011. X    va_list s;
  1012. X    int why;
  1013. X    char *fmt;
  1014. X
  1015. X    va_start(s);
  1016. X
  1017. X    why = va_arg (s, int);
  1018. X    fmt = va_arg (s, char *);
  1019. X    (void) fprintf (stderr, "%s: ", progname);
  1020. X    for (/* void */; *fmt; fmt++) {
  1021. X    if (*fmt != '%') {
  1022. X        (void) putc(*fmt,stderr);
  1023. X    } else if (*++fmt == 's') {
  1024. X        (void) fputs(va_arg(s,char *),stderr);
  1025. X    } else if (*fmt == 'c') {
  1026. X        (void) putc(va_arg(s,int),stderr);
  1027. X    } else if (*fmt == 'u') {
  1028. X        (void) fprintf(stderr,"%u",va_arg(s,unsigned));
  1029. X    } else if (*fmt == 'd') {
  1030. X        (void) fprintf(stderr,"%d",va_arg(s,int));
  1031. X    }
  1032. X    }
  1033. X    va_end(s);
  1034. X    (void) fprintf (stderr, "\n");
  1035. X    if (why != WARN)
  1036. X    exit (why);
  1037. X    (void) fflush (stderr);
  1038. X}
  1039. END_OF_FILE
  1040. if test 13362 -ne `wc -c <'opcom.c'`; then
  1041.     echo shar: \"'opcom.c'\" unpacked with wrong size!
  1042. fi
  1043. # end of 'opcom.c'
  1044. fi
  1045. if test -f 'srctoman' -a "${1}" != "-c" ; then 
  1046.   echo shar: Will not clobber existing file \"'srctoman'\"
  1047. else
  1048. echo shar: Extracting \"'srctoman'\" \(4703 characters\)
  1049. sed "s/^X//" >'srctoman' <<'END_OF_FILE'
  1050. X: srctoman - see comment below
  1051. X
  1052. X: process arguments
  1053. X
  1054. LOCAL=
  1055. HOST=
  1056. while :
  1057. do
  1058. X    case $1 in
  1059. X    -L) HOST=`hostname`;
  1060. X    HOST=`expr $HOST : '\([^.]*\)' | tr "[a-z]" "[A-Z]"`
  1061. X    LOCAL=LOCAL;;
  1062. X [0-9]) SECT=$1;;
  1063. X     -) LANG=$1; B='[#:]';;
  1064. X  -awk) LANG=$1; B='#';;
  1065. X    -c) LANG=$1; B='\/\*';;
  1066. X    -f) LANG=$1; B='[Cc]';;
  1067. X   -mk) LANG=$1; B='#';;
  1068. X -n|-t) LANG=$1; B='\\"';;
  1069. X    -p) LANG=$1; B='{';;
  1070. X    -r) LANG=$1; B='#';;
  1071. X    -C) LANG=$1; B=$2; shift;;
  1072. X    -*) ERROR="unknown option: $1"; break;;
  1073. X    "") ERROR="missing file argument"; break;;
  1074. X     *) break;;
  1075. X    esac
  1076. X    shift
  1077. done
  1078. X
  1079. X: check error status
  1080. X
  1081. case $ERROR in
  1082. X"") ;;
  1083. X *) echo "$0: $ERROR" 1>&2
  1084. X    echo "usage: $0 [-|-awk|-c|-f|-mk|-n|-p|-t|-r] [section] file(s)" 1>&2; exit 1;;
  1085. esac
  1086. X
  1087. X: set up for file suffix processing
  1088. X
  1089. case $LANG in
  1090. X"") sh='[:#]';    r='#';    rh=$r;    awk='#'; mk='#';
  1091. X    c='\/\*';    h=$c;    y=$c;    l=$c;
  1092. X    f='[Cc]';    fh=$f;    p='{';    ph=$p;
  1093. X    ms='\\"';    nr=$ms;    mn=$ms;    man=$ms;
  1094. esac
  1095. X
  1096. X: extract comments
  1097. X
  1098. for i in $*
  1099. do
  1100. X    case $LANG in
  1101. X    "") eval B\="\$`expr $i : '^.*\.\([^.]*\)$'`"
  1102. X    test "$B" || { echo "$0: unknown suffix: $i; assuming c" 1>&2; B=$c; }
  1103. X    esac
  1104. X    sed '
  1105. X    /^'"$B"'++/,/^'"$B"'--/!d
  1106. X    /^'"$B"'++/d
  1107. X    /^'"$B"'--/d
  1108. X    s/[     ]*$//
  1109. X    /^'"$B"' \([A-Z]\)/{
  1110. X    s//\1/
  1111. X    /^NAME/{
  1112. X        N
  1113. X        s/^.*\n'"$B"'[     ]*//
  1114. X        h
  1115. X        y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
  1116. X        s/,.*\([     ][0-9][     ]*\)$/ \1/
  1117. X        s/^.*$/.TH & '"$SECT $LOCAL $HOST"'\
  1118. X.ad\
  1119. X.fi\
  1120. X.SH NAME/
  1121. X        p
  1122. X        g
  1123. X        s/[     ][0-9][     ]*$//
  1124. X        a\
  1125. X\\-
  1126. X        p
  1127. X        d
  1128. X    }
  1129. X    /^SUMMARY/d
  1130. X    /^DESCRIPTION/s//.SH &\
  1131. X.ad\
  1132. X.fi/
  1133. X    /^BUGS/s//.SH &\
  1134. X.ad\
  1135. X.fi/
  1136. X    /^DIAGNOSTICS/s//.SH &\
  1137. X.ad\
  1138. X.fi/
  1139. X    /^[A-Z][A-Z][A-Z][^a-z]*$/s//.SH &\
  1140. X.na\
  1141. X.nf/
  1142. X    p
  1143. X    d
  1144. X    }
  1145. X    s/^'"$B"'[     ]*//
  1146. X    s/^[     ]*$//
  1147. X' $i
  1148. done | ./detab
  1149. X
  1150. exit
  1151. X
  1152. X:++
  1153. X: NAME
  1154. X:    srctoman 1
  1155. X: SUMMARY
  1156. X:    extract manual page from source file comment
  1157. X: PACKAGE
  1158. X:    source file maintentance tools
  1159. X: SYNOPSIS
  1160. X:    srctoman [-|-awk|-c|-f|-mk|-m|-n|-p|-t|-r] [section] file(s)
  1161. X: DESCRIPTION
  1162. X:    Sourcetoman converts comments in various programming languages to
  1163. X:    UNIX-style manual pages.
  1164. X:    The command processes comments in the style of newsource(1);
  1165. X:    its standard output is suitable for formatting with nroff(1) or 
  1166. X:    troff(1) using the "-man" macro package.  
  1167. X:    Typically, srctoman is integrated with make(1) scripts.
  1168. X:    If the option -L is given the text <hostname> (LOCAL) will be in
  1169. X:    the heading.
  1170. X:
  1171. X:    Source files are processed in the indicated order; if no
  1172. X:    files argument the command produces no output.
  1173. X:
  1174. X:    The source file language can be specified through a command-line
  1175. X:    option, or can be implied by the filename suffix.
  1176. X:    The expected start-of-comment symbol is shown in the last column.
  1177. X:
  1178. X: .nf
  1179. X    option    language    comment
  1180. X
  1181. X    -    shell        [:#]
  1182. X    -awk    awk        #
  1183. X    -c    c        /*
  1184. X    -f    fortran        [Cc]
  1185. X    -mk    make        #
  1186. X    -n    nroff        \\"
  1187. X    -p    pascal        {
  1188. X    -t    troff        \\"
  1189. X    -r    ratfor        #
  1190. X    -C    any language    next argument
  1191. X: .fi
  1192. X:
  1193. X: .nf
  1194. X    suffix    language    comment
  1195. X
  1196. X    .awk    awk        #
  1197. X    .c    c        /*
  1198. X    .f    fortran        [Cc]
  1199. X    .fh    fortran        [Cc]
  1200. X    .h    c        /*
  1201. X    .l    lex        /*
  1202. X    .man    nroff,troff    \\"
  1203. X    .mk    make        #
  1204. X    .me    nroff,troff    \\"
  1205. X    .ms    nroff,troff    \\"
  1206. X    .nr    nroff,troff    \\"
  1207. X    .p    pascal        {
  1208. X    .ph    pascal        {
  1209. X    .r    ratfor        #
  1210. X    .rh    ratfor        #
  1211. X    .sh    shell        [:#]
  1212. X    .y    yacc        /*
  1213. X: .fi
  1214. X:
  1215. X:    The required format of comments is discussed below, where SOC
  1216. X:    stands for the start-of-comment symbol of the language being used.
  1217. X:
  1218. X:    1) Start of manual: SOC, followed by `++'.
  1219. X:
  1220. X:    2) Section heading: SOC, blank, section name in upper case.
  1221. X:
  1222. X:    3) New paragraph: empty line or line with SOC only.
  1223. X:
  1224. X:    4) All other text: SOC and subsequent blanks or tabs are removed.
  1225. X:    Lines that do not start with SOC are left unchanged (useful for 
  1226. X:    inclusion of program text).
  1227. X:
  1228. X:    5) End of manual: SOC, followed by `--'.
  1229. X:    An end-of-comment may follow if the source file language requires this.
  1230. X:
  1231. X:    The following manual sections receive a special treatment:
  1232. X:    NAME and SUMMARY should appear at the beginning and in
  1233. X:    this order; DESCRIPTION, DIAGNOSTICS and BUGS will be
  1234. X:    right-margin adjusted.
  1235. X:    Other sections may be added freely without confusing srctoman.
  1236. X: COMMANDS
  1237. X:    sh(1), sed(1), detab(1)
  1238. X: SEE ALSO
  1239. X:    newsource(1), modsource(1), xman(1)
  1240. X:    The earlier commands new(1), mod(1), mkman(1) and dssman(1)
  1241. X:    by Ruud Zwart and Ben Noordzij (Erasmus University, Rotterdam) 
  1242. X: DIAGNOSTICS
  1243. X:    The program complaints if an unknown language is specified
  1244. X:    of if the language cannot be deduced from the file suffix.
  1245. X: AUTHOR(S)
  1246. X:    W.Z. Venema
  1247. X:    Eindhoven University of Technology
  1248. X:    Department of Mathematics and Computer Science
  1249. X:    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1250. X: CREATION DATE
  1251. X:    Fri Jan 17 22:59:27 MET 1986
  1252. X: LAST MODIFICATION
  1253. X:    Tue Mar 22 07:24:47 PST 1988
  1254. X: VERSION/RELEASE
  1255. X:    1.20
  1256. X:--
  1257. X
  1258. X
  1259. END_OF_FILE
  1260. if test 4703 -ne `wc -c <'srctoman'`; then
  1261.     echo shar: \"'srctoman'\" unpacked with wrong size!
  1262. fi
  1263. # end of 'srctoman'
  1264. fi
  1265. if test -f 'sysdep' -a "${1}" != "-c" ; then 
  1266.   echo shar: Will not clobber existing file \"'sysdep'\"
  1267. else
  1268. echo shar: Extracting \"'sysdep'\" \(268 characters\)
  1269. sed "s/^X//" >'sysdep' <<'END_OF_FILE'
  1270. X#define XSYSTEM
  1271. X#define XSYSLOG
  1272. X#define COMMANDS    "XCOMMANDS"
  1273. X#define PROFILE        "XPROFILE"
  1274. X
  1275. X#ifndef _NFILE
  1276. X#include <sys/param.h>
  1277. X#define _NFILE    NOFILE
  1278. X#endif
  1279. X
  1280. X#ifdef SYSV
  1281. X#include <string.h>
  1282. X#else
  1283. X#include <strings.h>
  1284. X#define strchr    index
  1285. X#define strrchr    rindex
  1286. X#endif
  1287. END_OF_FILE
  1288. if test 268 -ne `wc -c <'sysdep'`; then
  1289.     echo shar: \"'sysdep'\" unpacked with wrong size!
  1290. fi
  1291. # end of 'sysdep'
  1292. fi
  1293. echo shar: End of archive 1 \(of 1\).
  1294. cp /dev/null ark1isdone
  1295. MISSING=""
  1296. for I in 1 ; do
  1297.     if test ! -f ark${I}isdone ; then
  1298.     MISSING="${MISSING} ${I}"
  1299.     fi
  1300. done
  1301. if test "${MISSING}" = "" ; then
  1302.     echo You have the archive.
  1303.     rm -f ark[1-9]isdone
  1304. else
  1305.     echo You still need to unpack the following archives:
  1306.     echo "        " ${MISSING}
  1307. fi
  1308. ##  End of shell archive.
  1309. exit 0
  1310.